
define(`_R',  `r`'eval($1+$2)')
define(`_RS', `r`'eval($1+$2*$3)')

define(`MUL_Cmpx', `dnl: output $1; input $2 $3; tmp $4 $5

    mul_ieee $4, $2.xyzw, $3.xyzw
    mul_ieee $5, $2.xyzw, $3.yxwz
    sub $1.x_z_, $4.xxzz, $5.yyww
    add $1._y_w, $5.xxzz, $5.yyww
')

define(`FFT_2', `dnl input $1 $2; temp $3 

    mov $3, $1
    add $1, $3, $2
    sub $2, $3, $2
')

define(`FFT_4_ARRAY', `dnl: input $1 $2; temp $3 $4 $5

    FFT_2(_RS($1,0,$2), _RS($1,2,$2), $3)
    FFT_2(_RS($1,1,$2), _RS($1,3,$2), $3)

	mov $3, l1.xzxz
    MUL_Cmpx(_R($1,3,$2), _R($1,3,$2), $3, $4, $5)

    FFT_2(_RS($1,0,$2), _R($1,1,$2), $3)
    FFT_2(_RS($1,2,$2), _R($1,3,$2), $3)
')


define(`FFT_8_ARRAY', `dnl: input $1 $2; temp $3 $4 $5

    FFT_2(_RS($1,0,$2), _RS($1,4,$2), $3)
    FFT_2(_RS($1,1,$2), _RS($1,5,$2), $3)
    FFT_2(_RS($1,2,$2), _RS($1,6,$2), $3)
    FFT_2(_RS($1,3,$2), _RS($1,7,$2), $3)

	mov $3, l1.yzyz
    MUL_Cmpx(_RS($1,5,$2), _RS($1,5,$2), $3, $4, $5)
	mul_ieee _RS($1,5,$2), _RS($1,5,$2), l1.wwww

	mov $3, l1.xzxz
    MUL_Cmpx(_RS($1,6,$2), _RS($1,6,$2), $3, $4, $5)

	mov $3, l1.zzzz
    MUL_Cmpx(_RS($1,7,$2), _RS($1,7,$2), $3, $4, $5)
	mul_ieee _RS($1,7,$2), _RS($1,7,$2), l1.wwww

    FFT_4_ARRAY(eval($1+0*$2), $2, $3, $4, $5)
    FFT_4_ARRAY(eval($1+4*$2), $2, $3, $4, $5)
')

define(`FFT_16_ARRAY', `dnl: input $1 $2; temp $3 $4 $5

    FFT_4_ARRAY(eval($1+0*$2), eval(4*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+1*$2), eval(4*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+2*$2), eval(4*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+3*$2), eval(4*$2), $3, $4, $5)

	mov $3, l1.yzyz
    MUL_Cmpx(_RS($1,5,$2), _RS($1,5,$2), $3, $4, $5)
	mul_ieee _RS($1,5,$2), _RS($1,5,$2), l1.wwww

	mov $3, l1.xzxz
    MUL_Cmpx(_RS($1,6,$2), _RS($1,6,$2), $3, $4, $5)

	mov $3, l1.zzzz
    MUL_Cmpx(_RS($1,7,$2), _RS($1,7,$2), $3, $4, $5)
	mul_ieee _RS($1,7,$2), _RS($1,7,$2), l1.wwww

	mov $3, l2.yzyz
    MUL_Cmpx(_RS($1,9,$2), _RS($1,9,$2), $3, $4, $5)

	mov $3, l1.yzyz
    MUL_Cmpx(_RS($1,10,$2), _RS($1,10,$2), $3, $4, $5)
	mul_ieee _RS($1,10,$2), _RS($1,10,$2), l1.wwww

	mov $3, l2.xwxw
    MUL_Cmpx(_RS($1,11,$2), _RS($1,11,$2), $3, $4, $5)

	mov $3, l2.xwxw
    MUL_Cmpx(_RS($1,13,$2), _RS($1,13,$2), $3, $4, $5)

	mov $3, l1.zzzz
    MUL_Cmpx(_RS($1,14,$2), _RS($1,14,$2), $3, $4, $5)
	mul_ieee _RS($1,14,$2), _RS($1,14,$2), l1.wwww

	mov $3, l2.wxwx
    MUL_Cmpx(_RS($1,15,$2), _RS($1,15,$2), $3, $4, $5)

    FFT_4_ARRAY(eval($1+ 0*$2), eval($2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+ 4*$2), eval($2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+ 8*$2), eval($2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+12*$2), eval($2), $3, $4, $5)
')

define(`FFT_32_ARRAY', `dnl: input $1 $2; temp $3 $4 $5

    FFT_4_ARRAY(eval($1+0*$2), eval(8*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+1*$2), eval(8*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+2*$2), eval(8*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+3*$2), eval(8*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+4*$2), eval(8*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+5*$2), eval(8*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+6*$2), eval(8*$2), $3, $4, $5)
    FFT_4_ARRAY(eval($1+7*$2), eval(8*$2), $3, $4, $5)

	mov $3, l10.xyxy
    MUL_Cmpx(_RS($1,9,$2), _RS($1,9,$2), $3, $4, $5)

	mov $3, l10.zwzw
    MUL_Cmpx(_RS($1,10,$2), _RS($1,10,$2), $3, $4, $5)

	mov $3, l11.xyxy
    MUL_Cmpx(_RS($1,11,$2), _RS($1,11,$2), $3, $4, $5)
	
	mov $3, l1.xzxz
    MUL_Cmpx(_RS($1,12,$2), _RS($1,12,$2), $3, $4, $5)
	
	mov $3, l11.zwzw
    MUL_Cmpx(_RS($1,13,$2), _RS($1,13,$2), $3, $4, $5)
	
	mov $3, l12.xyxy
    MUL_Cmpx(_RS($1,14,$2), _RS($1,14,$2), $3, $4, $5)
	
	mov $3, l12.zwzw
    MUL_Cmpx(_RS($1,15,$2), _RS($1,15,$2), $3, $4, $5)
	
	mov $3, l13.xyxy
    MUL_Cmpx(_RS($1,17,$2), _RS($1,17,$2), $3, $4, $5)
	
	mov $3, l13.zwzw
    MUL_Cmpx(_RS($1,18,$2), _RS($1,18,$2), $3, $4, $5)
	
	mov $3, l14.xyxy
    MUL_Cmpx(_RS($1,19,$2), _RS($1,19,$2), $3, $4, $5)
	
	mov $3, l14.zwzw
    MUL_Cmpx(_RS($1,20,$2), _RS($1,20,$2), $3, $4, $5)
	
	mov $3, l15.xyxy
    MUL_Cmpx(_RS($1,21,$2), _RS($1,21,$2), $3, $4, $5)
	
	mov $3, l15.zwzw
    MUL_Cmpx(_RS($1,22,$2), _RS($1,22,$2), $3, $4, $5)
	
	mov $3, l16.xyxy
    MUL_Cmpx(_RS($1,23,$2), _RS($1,23,$2), $3, $4, $5)
	
	mov $3, l16.zwzw
    MUL_Cmpx(_RS($1,25,$2), _RS($1,25,$2), $3, $4, $5)
	
	mov $3, l17.xyxy
    MUL_Cmpx(_RS($1,26,$2), _RS($1,26,$2), $3, $4, $5)
	
	mov $3, l17.zwzw
    MUL_Cmpx(_RS($1,27,$2), _RS($1,27,$2), $3, $4, $5)
	
	mov $3, l18.xyxy
    MUL_Cmpx(_RS($1,28,$2), _RS($1,28,$2), $3, $4, $5)
	
	mov $3, l18.zwzw
    MUL_Cmpx(_RS($1,29,$2), _RS($1,29,$2), $3, $4, $5)
	
	mov $3, l19.xyxy
    MUL_Cmpx(_RS($1,30,$2), _RS($1,30,$2), $3, $4, $5)
	
	mov $3, l19.zwzw
    MUL_Cmpx(_RS($1,31,$2), _RS($1,31,$2), $3, $4, $5)
	
    FFT_8_ARRAY(eval($1+ 0*$2), eval($2), $3, $4, $5)
    FFT_8_ARRAY(eval($1+ 8*$2), eval($2), $3, $4, $5)
    FFT_8_ARRAY(eval($1+16*$2), eval($2), $3, $4, $5)
    FFT_8_ARRAY(eval($1+24*$2), eval($2), $3, $4, $5)
')

define(`argn', `ifelse(`$1', 1, ``$2'',
`argn(decr(`$1'), shift(shift($@)))')')

define(`REV_BITS_4', `argn(incr($1), `0', `2', `1', `3')')

define(`REV_BITS_8', `argn(incr($1), 
    `0', `4', `2', `6', `1', `5', `3', `7')
')

define(`REV_BITS_16', `argn(incr($1), 
    `0', `8', `4', `12', `2', `10', `6', `14', 
    `1', `9', `5', `13', `4', `11', `7', `15')
')

define(`REV_BITS_32', `argn(incr($1), 
    `0', `16',  `8', `24', `4', `20', `12', `28', 
    `2', `18', `10', `26', `6', `22', `14', `30',
    `1', `17',  `9', `25', `5', `21', `13', `29',
    `3', `19', `11', `27', `7', `23', `15', `31')
')

